
package Servidor;
import dao.MySqlObjetivoDAO;
import datos.*;
import interfaz.VentanaPrincipal;
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ThreadServidor extends Thread
{
     VentanaPrincipal ventana;
     Socket scli=null;
     Socket scli2=null;
     DataInputStream entrada=null;
     DataOutputStream salida=null;
     DataOutputStream salida2=null;
     private Jugador jugador = null;
     public static Vector<ThreadServidor> clientesActivos=new Vector();
     public static Vector<String> turno = null;
     String nameUser;
     ArrayList mundo;
     Pais[] paises;
     
     Vector<String> paisess = new Vector<String>();

//     private static Objetivo obj;
     private static MySqlObjetivoDAO mod = new MySqlObjetivoDAO();

     public ThreadServidor(Socket scliente,Socket scliente2, VentanaPrincipal vp)
     {
        ventana = vp;
        scli=scliente;
        scli2=scliente2;
        nameUser="";
        clientesActivos.add(this);
     }

    public Jugador getJugador() {
        return jugador;
    }
    
     public String getNameUser()
     {
       return nameUser;
     }    
     
     public void run()
     {
    	try
    	{
          entrada=new DataInputStream(scli.getInputStream());
          salida=new DataOutputStream(scli.getOutputStream());
          salida2=new DataOutputStream(scli2.getOutputStream());
          this.guardarJugador();
    	}
    	catch (IOException e) {  e.printStackTrace();     }
    	
        int opcion=0,numUsers=0;
        String amigo="",mencli="";
                
    	while(true)
    	{
          try
          {
             opcion=entrada.readInt();
             switch(opcion)
             {
                case 1://envio de mensage a todos
                   mencli=entrada.readUTF();
                   enviaMsg(mencli);
                   break;
                case 2://envio de lista de activos
                   numUsers=clientesActivos.size();
                   salida.writeInt(numUsers);
                   for(int i=0;i<numUsers;i++)
                      salida.writeUTF(clientesActivos.get(i).nameUser);
                   break;
                case 3: // envia mensage a uno solo
                   amigo=entrada.readUTF();//captura nombre de amigo
                   mencli=entrada.readUTF();//mensage enviado
                   enviaMsg(amigo,mencli);
                   break;
                    
                case 9:
                    this.devolverNombresColores();
                    break; 
                case 10:
                    String nombre=entrada.readUTF();
                    String color=entrada.readUTF();
                    this.actualizarColor(nombre, color);
                    break;
                case 11:
                    this.avisarColores();
                    break;
                case 12:
                    this.avisarComenzarPartida();
                    break;
                case 13:
                    this.gestionarJuego();
                    break;
                 case 14: // acualizar pais
                     String pais = entrada.readUTF();
                     String direccion = entrada.readUTF();
                     int ejercito = entrada.readInt();
                     this.actualizarLabel(pais, direccion, ejercito);
                     break;
                 case 15:
                     int proxTurno = entrada.readInt();
                     this.asignarProximoTurno(proxTurno);
                     break;
                 case 16:// nueva ronda
                     this.comenzarNuevaRonda();
                     break;
                 case 17:// Avisar ataque
                     String pais1 = entrada.readUTF();
                     String color1 = entrada.readUTF();
                     int ejercito1 = entrada.readInt();
                     String pais2 = entrada.readUTF();
                     String color2 = entrada.readUTF();
                     int ejercito2 = entrada.readInt();
                     System.out.println(pais1+ color1+ ejercito1+ pais2+ color2+ ejercito2);
                     this.actualizarAtaque(pais1, color1, ejercito1, pais2, color2, ejercito2);
                     break;
                 case 18:// avisar dados a oponente
                     String colorOponente = entrada.readUTF();
                     int[] dadosOrigen = new int[entrada.readInt()];
                     for (int i = 0; i < dadosOrigen.length; i++) {
                        dadosOrigen[i] = entrada.readInt();
                     }
                     int[] dadosDestino = new int[entrada.readInt()];
                     for (int i = 0; i < dadosDestino.length; i++) {
                        dadosDestino[i] = entrada.readInt();
                     }
                     this.actualizarDadosOponente(dadosOrigen, dadosDestino, colorOponente);
                     break;
                 case 19:// avisar verificar mision
                     this.verificarMision();
                     break;
                 case 20:
                     String nom=entrada.readUTF();
                     String objetivo=entrada.readUTF();
                     this.avisarVictoria(nom, objetivo);
                     break;
             }
          }
          catch (IOException e) {System.out.println("El cliente termino la conexion");break;}
    	}
    	clientesActivos.removeElement(this);
    	try
    	{
          ventana.actualizarChat("Se desconecto un usuario");
          scli.close();
    	}	
        catch(Exception et){
            ventana.actualizarChat("no se puede cerrar el socket");
        }
     }
     
     public void enviaMsg(String mencli2)
     {
        ThreadServidor user=null;
        for(int i=0;i<clientesActivos.size();i++)
        {
           try{
              user=clientesActivos.get(i);
              user.salida2.writeInt(1);//opcion de mensage 
              user.salida2.writeUTF(""+this.getNameUser()+" >"+ mencli2 + "\n");
            }catch (IOException e) {e.printStackTrace();}
        }
     }
     
   private void enviaMsg(String amigo, String mencli) 
   {
      ThreadServidor user=null;
        for(int i=0;i<clientesActivos.size();i++)
        {           
           try{
              user=clientesActivos.get(i);
              if(user.nameUser.equals(amigo))
              {
                 user.salida2.writeInt(3);//opcion de mensage amigo   
                 user.salida2.writeUTF(this.getNameUser());
                 user.salida2.writeUTF(""+this.getNameUser()+">"+mencli);
              }
            }catch (IOException e) {e.printStackTrace();}
        }
   }

    private void guardarJugador() {
        String nombre = "";
        try {
            nombre = entrada.readUTF();
            nameUser = nombre;
            jugador = new Jugador(nombre);
        } catch (IOException ex) {
            Logger.getLogger(ThreadServidor.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void actualizarColor(String nombre, String color) {
        ThreadServidor user=null;
        for(int i=0;i<clientesActivos.size();i++)
        {         
            user=clientesActivos.get(i);
            if(user.getJugador().getNombre().equals(nombre)){
                user.getJugador().setColor(color);
                break;
            }
        }
    }

    private void devolverNombresColores() {
        ThreadServidor user=null;
        String enviar = "";
        try {
            salida.writeInt(clientesActivos.size());
            for(int i=0;i<clientesActivos.size();i++){
                user = clientesActivos.get(i);
                enviar = user.getJugador().getNombre();
                salida.writeUTF(enviar);
                enviar = user.getJugador().getColor();
                salida.writeUTF(enviar);
            } 
        } catch (IOException ex) {
            Logger.getLogger(ThreadServidor.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void avisarColores() {
        ThreadServidor user=null;
        String[] nombresColores = new String[clientesActivos.size()*2];
        int indice = 0;
        for(int i=0;i<clientesActivos.size();i++){
            user = clientesActivos.get(i);
            nombresColores[indice] = user.getJugador().getNombre();
            indice++;
            nombresColores[indice] = user.getJugador().getColor();
            indice++;
        }
        for(int j=0;j<clientesActivos.size();j++){  
            try{
                user=clientesActivos.get(j);
                user.salida2.writeInt(4);//opcion actualizar colores
                user.salida2.writeInt(clientesActivos.size());
                for(int k=0;k<clientesActivos.size()*2;k++){  
                    user.salida2.writeUTF(nombresColores[k]);
                }
            }catch (IOException e) {e.printStackTrace();}
        }
    }

    private void avisarComenzarPartida() {
        ThreadServidor user=null;
        for(int i=0;i<clientesActivos.size();i++){
            try{
                user=clientesActivos.get(i);
                user.salida2.writeInt(5);//opcion avisar comezar partida
            }catch (IOException e) {e.printStackTrace();}
        
        }
    }

    private void gestionarJuego() {
        crearPaises();
        int sobra = 0;
        int paisesXJugador = (int)(50/clientesActivos.size());
        if(paisesXJugador*clientesActivos.size() != 50){
            sobra = 50 - paisesXJugador*clientesActivos.size();
        }
        this.asignarPaises(paisesXJugador, clientesActivos.size(), sobra);
        this.asignarTurnos();
      
        asignarMision();
        
    }

    private void asignarPaises(int paisesXJugador, int cantJugadores, int sobra) {
        //asigno la cantidad de paises por jugador
        String color = "";
        ThreadServidor user=null;
        ThreadServidor user2=null;
     //   String emanuel="";
        
        
        //Lo estoy cambiando xq me tira algunos errores a veces quedan paises sin asignar y tamb veo q asignas numeros a los paises como id de jugador en ves del nombre de jugador
        String pais = "";
        int random = 0;
        for(int i=0; i<cantJugadores; i++){
            user = clientesActivos.get(i);
            color = user.getJugador().getColor();
            for(int j=0; j<paisesXJugador; j++){
                random = (int)(Math.random()*paisess.size());
                pais = paisess.get(random);
                for (int k = 0; k < clientesActivos.size(); k++) {
                    try{
                        user2=clientesActivos.get(k);
                        user2.salida2.writeInt(6);//opcion avisar asignar paises
                        user2.salida2.writeUTF(color);
                        user2.salida2.writeUTF(pais);
                    }catch (IOException e) {e.printStackTrace();}
                }
                paisess.remove(pais);
            }   
        }
        for (int i = 0; i < sobra; i++) {
            random = (int)(Math.random()*cantJugadores);
            user = clientesActivos.get(random);
            color = user.getJugador().getColor();
            random = (int)(Math.random()*paisess.size());
            pais = paisess.get(random);
            for (int k = 0; k < clientesActivos.size(); k++) {
                try{
                    user2=clientesActivos.get(k);
                    user2.salida2.writeInt(6);//opcion avisar asignar paises
                    user2.salida2.writeUTF(color);
                    user2.salida2.writeUTF(pais);
                }catch (IOException e) {e.printStackTrace();}
            }
            paisess.remove(pais);
        }
    }

     public void crearPaises()
    {
        paisess.add("Francia");
        paisess.add("Rusia");
        paisess.add("Italia");
        paisess.add("Espania");
        paisess.add("Islandia");
        paisess.add("GranBretania");
        paisess.add("Alemania");
        paisess.add("Polonia");
        paisess.add("Suecia");
        paisess.add("Siberia");
        paisess.add("Tartaria");
        paisess.add("Japon");
        paisess.add("Mongolia");
        paisess.add("Taimir");
        paisess.add("Aral");
        paisess.add("Gobi");
        paisess.add("Iran");
        paisess.add("Turquia");
        paisess.add("Israel");
        paisess.add("Arabia");
        paisess.add("Katchatka");
        paisess.add("China");
        paisess.add("India");
        paisess.add("Malasia");
        paisess.add("Java");
        paisess.add("Sumatra");
        paisess.add("Borneo");
        paisess.add("Australia");
        paisess.add("Zaire");
        paisess.add("Sudafrica");
        paisess.add("Madagascar");
        paisess.add("Etiopia");
        paisess.add("Egipto");
        paisess.add("Sahara");
        paisess.add("Peru");
        paisess.add("Chile");
        paisess.add("Uruguay");
        paisess.add("Colombia");
        paisess.add("Terranova");
        paisess.add("Oregon");
        paisess.add("NuevaYork");
        paisess.add("Mexico");
        paisess.add("Labrador");
        paisess.add("Groenlandia");
        paisess.add("Canada");
        paisess.add("California");
        paisess.add("Brasil");
        paisess.add("Alaska");
        paisess.add("Yukon");
        paisess.add("Argentina");
    }
    private void asignarTurnos() {
        turno = new Vector<String>();
        Vector<ThreadServidor> temp = new Vector<ThreadServidor>();
        for (int i = 0; i < clientesActivos.size(); i++) {
            temp.add(clientesActivos.get(i));
        }
        for (int i = 0; i < clientesActivos.size(); i++) {
            int num = (int)(Math.random()*temp.size());
            turno.add(temp.get(num).getNameUser());
            temp.remove(num);
        }
        this.comunicarTurnos();
    }

    private void comenzarNuevaRonda(){
        Vector<String> temp = new Vector<String>();
        for (int i = 1; i < turno.size(); i++) { //Comienza en el 1 y al final del for agrega el 1ro q pasa a ser ultimo
            temp.add(turno.get(i));
        }
        temp.add(turno.get(0));
        turno = temp;
        this.comunicarTurnos();
    }

    private void comunicarTurnos() {
        ThreadServidor user=null;
        String[] colores = this.averiguarColor();
        for(int i=0;i<clientesActivos.size();i++){
            try{
                user=clientesActivos.get(i);
                user.salida2.writeInt(7);//opcion comunicar turnos
                user.salida2.writeInt(turno.size());
                for (int j = 0; j < turno.size(); j++) {
                    user.salida2.writeUTF(turno.get(j));
                    user.salida2.writeUTF(colores[j]);
                }
            }catch (IOException e) {e.printStackTrace();}
        }
    }

//    private Objetivo[] crearMisiones()
//    {
//        //NA, SA, E, Asia, africa, Oceania
//        Objetivo mision[]=new Objetivo[9];
//        mision[0]=new Objetivo("Ocupar america del norte, 2 paises de oceania y 4 de asia", 10, 0, 0, 4, 0, 2, null);
//        mision[1]=new Objetivo("Ocupar 2 paises de oceania, 2 paises de africa, 2 paises de america del sur, 3 paises de europa, 4 paises de america del norte y 3 paises de asia", 4, 2, 3, 3, 2, 2, null);
//        mision[2]=new Objetivo("Ocupar america del sur, africa y 4 paises de asia", 0, 6, 0, 4, 6, 0, null);
//        mision[3]=new Objetivo("Ocupar oceania, america del norte, y 2 paises de europa", 10, 0, 2, 0, 0, 4, null);
//        mision[4]=new Objetivo("Ocupar africa, 5 paises de america del norte y 4 paises de europa", 5, 0, 4, 0, 6, 0, null);
//        mision[5]=new Objetivo("Ocupar america del sur, 7 paises de europa, y 3 paises de america del norte", 3, 6, 7, 0, 0, 0, null);
//        mision[6]=new Objetivo("Ocupar oceania, africa y 5 paises de america del norte", 5, 0, 0, 0, 6, 4, null);
//        mision[7]=new Objetivo("Ocupar europa, 4 apises de asia, y 2 paises de america del sur", 0, 2, 9, 4, 0, 0, null);
//        mision[8]=new Objetivo("Ocupar asia y 2 paises de america del sur", 0, 2, 0, 15, 0, 0, null);
//
//
//
//       return mision;
//    }

    private void asignarMision() 
    {
        int aux= 0;
        Objetivo objet = null;
        LinkedList idObj = new LinkedList();
        for (int j = 0; j < 9; j++) {
            idObj.addLast(j+1);
        }
        ThreadServidor user2=null;
        int cantidad =  clientesActivos.size();
        for(int i=0; i<cantidad; i++)
        {
            try{
                aux = (int)(Math.random()*idObj.size()+1);
                objet = new Objetivo(aux);
                objet = mod.find(objet);
                user2 = clientesActivos.get(i);
                user2.salida2.writeInt(8);
                user2.salida2.writeUTF(objet.getDescripcion());
                user2.salida2.writeInt(objet.getCantPaisNorteAmerica());
                user2.salida2.writeInt(objet.getCantPaisSudAmerica());
                user2.salida2.writeInt(objet.getCantPaisEuropa());
                user2.salida2.writeInt(objet.getCantPaisAsia());
                user2.salida2.writeInt(objet.getCantPaisAfrica());
                user2.salida2.writeInt(objet.getCantPaisOceania());
                //ver si a aux hay q restarle 1 cuando ande todo
                idObj.remove(aux-1);
            }catch(IOException e){}
        }
    }

    private void actualizarLabel(String pais, String direccion, int ejercito) {
        ThreadServidor user=null;
        for(int i=0; i<clientesActivos.size(); i++)
        {
            try{
                user=clientesActivos.get(i);
                if(user != this){
                    user.salida2.writeInt(9);// actualizar label
                    user.salida2.writeUTF(pais);
                    user.salida2.writeUTF(direccion);
                    user.salida2.writeInt(ejercito);
                }
            }catch(IOException e){}
        }
    }

    private void asignarProximoTurno(int proxTurno) {
        ThreadServidor user=null;
        for(int i=0; i<clientesActivos.size(); i++)
        {
            try{
                user=clientesActivos.get(i);
                if(user != this){
                    user.salida2.writeInt(10);// proximo turno
                    user.salida2.writeInt(proxTurno);
                }
            }catch(IOException e){}
        }
    }

    private void actualizarAtaque(String pais1, String color1, int ejercito1, String pais2, String color2, int ejercito2) {
        ThreadServidor user=null;
        for(int i=0; i<clientesActivos.size(); i++)
        {
            try{
                user=clientesActivos.get(i);
                if(user != this){
                    user.salida2.writeInt(11);// actualizar ataque
                    user.salida2.writeUTF(pais1);
                    user.salida2.writeUTF(color1);
                    user.salida2.writeInt(ejercito1);
                    user.salida2.writeUTF(pais2);
                    user.salida2.writeUTF(color2);
                    user.salida2.writeInt(ejercito2);
                }
            }catch(IOException e){}
        }
    }

    private void actualizarDadosOponente(int[] dadosOrigen, int[] dadosDestino, String colorOponente) {
        ThreadServidor user=null;
        String colorOpon = "";
        for(int i=0; i<clientesActivos.size(); i++)
        {
            try{
                user=clientesActivos.get(i);
                colorOpon = user.getJugador().getColor();
                if(colorOpon.equalsIgnoreCase(colorOponente)){
                    System.out.println("Enviamos datos de dados al oponente");
                    user.salida2.writeInt(12);// actualizar dados oponente
                    int enviar = dadosOrigen.length;
                    System.out.println(enviar);
                    user.salida2.writeInt(enviar);
                    for (int j = 0; j < dadosOrigen.length; j++) {
                        enviar = dadosOrigen[j];
                        System.out.println(enviar);
                        user.salida2.writeInt(enviar);
                    }
                    enviar = dadosDestino.length;
                    System.out.println(enviar);
                    user.salida2.writeInt(enviar);
                    for (int j = 0; j < dadosDestino.length; j++) {
                        enviar = dadosDestino[j];
                        System.out.println(enviar);
                        user.salida2.writeInt(enviar);
                    }
                    break;
                }
            }catch(IOException e){}
        }
    }

    private void verificarMision() {
        ThreadServidor user=null;
        for(int i=0; i<clientesActivos.size(); i++)
        {
            try{
                user=clientesActivos.get(i);
                if(user != this){
                    user.salida2.writeInt(13);// verificar mision
                }
            }catch(IOException e){}
        }
    }

    private String[] averiguarColor() {
        String[] colores = new String[turno.size()];
        ThreadServidor user=null;
        String nom = "";
        for(int i=0; i < colores.length; i++)
        {
            for (int j = 0; j < colores.length; j++) {
                user=clientesActivos.get(j);
                nom = user.getJugador().getNombre();
                if(user.getJugador().getNombre().equalsIgnoreCase(turno.get(i))){
                    colores[i] = user.getJugador().getColor();
                }
            }
        }
        return colores;
    }

  

    private void avisarVictoria(String nom, String objetivo) 
    {   ThreadServidor user=null;
        for(int i=0; i<clientesActivos.size(); i++)
        {
            try{
                user=clientesActivos.get(i);
                if(user != this){
                    user.salida2.writeInt(14);// verificar mision
                    user.salida2.writeUTF(nom);
                    user.salida2.writeUTF(objetivo);
                }
            }catch(IOException e){}
        }
        
    }
}

    